﻿
using System;
using System.IO;
using System.Web;
using System.Xml;
using System.Data;
using System.Data.Common;
using System.Configuration;
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using SyCODE.Component.DataFactory;
using SyCODE.SearchEngine;
using SyCODE.SearchEngine.Store;
using System.Text;
using SyCODE.Component;

/// <summary>
/// SyCODE 的摘要说明
/// </summary>
namespace SyCODE.Blog
{
    /// <summary>
    /// Search.aspx 的处理程序
    /// 作用：
    ///   按照关键搜索符合条件的日志
    ///   接受GET访问
    /// 传入的参数包括
    ///   wd 用户输入的关键字，支持UTF-8,GBK等URL编码，支持未编码的文字内容
    ///   p 搜索结果的分页页码，可选参数，默认为1
    ///   sz 每页的结果数，可选参数，默认为20
    /// </summary>
    public class Search : IHttpHandler
    {
        #region IHttpHandler 成员

        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            //设置客户端缓存时间，单位：秒
            context.Response.Expires = 2880;
            NameValueCollection request = context.Request.QueryString;

            int page = 1;
            int size = 20;

            if (!String.IsNullOrEmpty(request["p"]))
            {
                //分页页码
                Int32.TryParse(request["p"], out page);
            }
            if (!String.IsNullOrEmpty(request["sz"]))
            {
                //获得分页大小
                Int32.TryParse(request["sz"], out size);
            }

            //指定输出内容类型
            context.Response.ContentType = "text/xml";

            XmlTextWriter writer = new XmlTextWriter(context.Response.OutputStream, context.Response.ContentEncoding);
            writer.WriteStartDocument();
            writer.WriteProcessingInstruction("xml-stylesheet", "type='text/xsl' href='/ui/common/search.xsl'");

            writer.WriteStartElement("html");

            //读取关键字部分的内容，兼容utf-8和gbk编码方式
            string wd = String.Empty, word = String.Empty;
            if (request["wd"] != null)
            {
                string owd = context.Request.RawUrl.Substring(context.Request.RawUrl.LastIndexOf("wd=", StringComparison.OrdinalIgnoreCase) + 3);
                int ep = owd.IndexOf('&');
                if (ep > 0)
                    owd = owd.Substring(0, ep);

                wd = Function.UrlDecode(owd);

                word = Regex.Replace(Regex.Replace(wd, @"[^\w\d\s\+\.#]+", " "), @"\s+", " ").Trim();
            }

            if (word.Length > 0)
            {
                DateTime start = DateTime.Now;
                Documents docs = Simple.Search(word);
                DateTime end = DateTime.Now;
                TimeSpan span = end - start;
                WriteHeadAttributes(writer, page, wd, docs.Keywords, size, docs.Count, span.TotalSeconds.ToString("f3"));

                writer.WriteStartElement("body");

                //开始输出正文内容
                int range = page * size;
                for (int i = range - size; i < range && i < docs.Count; i++)
                {
                    WriteBodyElements(writer, docs[i], wd);
                }

                //输出供搜索引擎使用的下一页的链接
                if (docs.Count > range)
                {
                    writer.WriteStartElement("a");
                    writer.WriteAttributeString("href", "search.aspx?p=" + (page + 1).ToString() + "&wd=" + HttpUtility.HtmlEncode(wd).Replace("+", "%2b"));
                    writer.WriteString("next page");
                    writer.WriteEndElement();
                }

                writer.WriteEndElement();
            }
            else
            {
                //如果没有输入关键字则输出空白内容
                WriteHeadAttributes(writer, page, wd, "", size, 0, "0");
            }

            writer.WriteEndElement();

            writer.WriteEndDocument();
            writer.Flush();
        }

        /// <summary>
        /// 输出HTML的HEAD区
        /// </summary>
        /// <param name="writer">XML编写器</param>
        /// <param name="page">页码</param>
        /// <param name="wd">原始关键字</param>
        /// <param name="keywords">经过分词处理的关键字</param>
        /// <param name="size">分页大小</param>
        /// <param name="count">搜索结果数量</param>
        /// <param name="span">搜索过程的耗时时间，单位：豪秒</param>
        private void WriteHeadAttributes(XmlTextWriter writer, int page, string wd, string keywords, int size, int count, string span)
        {
            writer.WriteAttributeString("page", page.ToString());
            writer.WriteAttributeString("count", count.ToString());
            writer.WriteAttributeString("code", HttpUtility.UrlEncode(wd));
            writer.WriteAttributeString("span", span);
            writer.WriteAttributeString("size", size.ToString());

            writer.WriteStartElement("head");

            writer.WriteStartElement("meta");
            writer.WriteAttributeString("http-equiv", "Content-Type");
            writer.WriteAttributeString("content", "text/html; charset=utf-8");
            writer.WriteEndElement();

            writer.WriteStartElement("title");
            writer.WriteString(wd + " - Powered By X3BLOG");
            writer.WriteEndElement();

            writer.WriteStartElement("meta");
            writer.WriteAttributeString("name", "keywords");
            writer.WriteAttributeString("content", keywords.Replace(' ', ','));
            writer.WriteEndElement();

            writer.WriteStartElement("meta");
            writer.WriteAttributeString("name", "description");
            writer.WriteAttributeString("content", wd);
            writer.WriteEndElement();

            writer.WriteEndElement();
        }

        /// <summary>
        /// 输出正文内容项
        /// </summary>
        /// <param name="writer">XML编写器</param>
        /// <param name="doc">结果项文档</param>
        /// <param name="wd">关键字</param>
        private void WriteBodyElements(XmlTextWriter writer, Document doc, string wd)
        {
            writer.WriteStartElement("p");

            writer.WriteStartElement("a");
            writer.WriteAttributeString("href", "/" + doc.Author + "/topic/" + doc.ID);
            writer.WriteString(doc.Title);
            writer.WriteEndElement();

            writer.WriteStartElement("a");
            writer.WriteAttributeString("href", "/" + doc.Author);
            writer.WriteString(doc.Name);
            writer.WriteEndElement();

            writer.WriteStartElement("a");
            writer.WriteAttributeString("href", "/" + doc.Author + "/rss");
            writer.WriteString("rss");
            writer.WriteEndElement();

            writer.WriteStartElement("a");
            writer.WriteAttributeString("href", "/lsearch.aspx?u=" + doc.Author + "&wd=" + HttpUtility.HtmlEncode(wd).Replace("+", "%2b"));
            writer.WriteString(wd);
            writer.WriteEndElement();

            writer.WriteStartElement("a");
            writer.WriteAttributeString("href", "/search.aspx?wd=" + HttpUtility.HtmlEncode(doc.Tag.Replace(" ","")).Replace("+", "%2b"));
            writer.WriteString(doc.Tag);
            writer.WriteEndElement();

            WriteTagElements(writer, doc.Tag);

            writer.WriteStartElement("p");
            writer.WriteCData(doc.Body);
            writer.WriteEndElement();

            writer.WriteStartElement("span");
            writer.WriteString(doc.LastIndex.ToString(StringResource.GetField("datetimeformat")));
            writer.WriteEndElement();

            writer.WriteEndElement();
        }

        /// <summary>
        /// 输出日志的标签
        /// </summary>
        /// <param name="writer">xml编写器</param>
        /// <param name="tag">标签</param>
        private void WriteTagElements(XmlTextWriter writer, string tag)
        {
            writer.WriteStartElement("div");
            string[] tags = tag.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

            for (int i = 0; i < tags.Length; i++)
            {
                writer.WriteStartElement("a");
                writer.WriteAttributeString("href", "/search.aspx?wd=" + HttpUtility.HtmlEncode(tags[i]).Replace("+", "%2b"));
                writer.WriteString(tags[i]);
                writer.WriteEndElement();
            }
            writer.WriteEndElement();
        }
        #endregion
    }
}